let _Vue = null

export default class VueRouter {
    static install(Vue) {
        // 判断插件是否被安装
        if (VueRouter.install.installed) {
            return 
        }
        VueRouter.install.installed = true
        // 把Vue 构造函数记录到全局变量 
        _Vue = Vue
        // 把创建Vue实例时传入的router对象注入到Vue实例上
        // 并且因为当前this指向问题，所以采用混入的方式来找到当前实例对象，将this.$options.router挂载到vue原型上
        _Vue.mixin({
            beforeCreate () {
                // 只需要挂载一次，因为每个组件都会有 beforeCreate 生命周期，所以应该判断Vue实例属性是否存在router， 存在才挂载到原型
                if(this.$options.router) {
                    _Vue.prototype.$router = this.$options.router
                    // 挂载完成之后，执行初始化
                    this.$options.router.init()
                }
            }
        })
    }

    constructor(options) {
        // 实例化时传入的路由规则配置项
        this.options = options
        // 路由组件地址
        this.routeMap = {}
        // 创建响应式对象，存储当前路由实例
        this.data = _Vue.observable({
            current: "/"
        })
    }
    // 初始化调用
    init() {
        this.createRouteMap()
        // 传入全局Vue实例
        this.initComponents(_Vue)
        // 监听地址栏变化，前进和后退都会触发
        this.initEvent()
    }

    createRouteMap() {
        // 遍历所有的路由规则，把路由规则解析成键值对存储到routeMap中
        this.options.routes.forEach(element => {
            this.routeMap[element.path] = element.component
        });
    }
    
    initComponents(Vue) {
        const self = this
        Vue.component("router-link", {
            props: {
                to: String
            },
            render (h) {
                return h("a", {
                    attrs: {
                        href:  self.options.mode === "history" ? this.to : `#${this.to}`
                    },
                    on: {
                        click: this.clickHandler
                    }
                }, [this.$slots.default])
            },
            methods: {
                clickHandler(e) {
                    if(self.options.mode === "history") {
                        history.pushState({}, "", this.to)
                        this.$router.data.current = this.to
                        e.preventDefault()
                    }
                }
            }
            // template: "<a :href='to'><slot></slot></a>" // 需要在配置文件生命vue版本 runtimeCompiler 是否使用包含运行时编译器的 Vue 构建版本
        })
        Vue.component("router-view", {
            render (h) {
                const component = self.routeMap[self.data.current]
                // h 可将组件直接转换为虚拟dom
                return h(component)
            }
        })
    }

    initEvent() {
        if (this.options.mode === "history") {
            window.addEventListener("popstate", () => {
                this.data.current = window.location.pathname
            })
        } else {
            // 监听 页面加载完成，保证初始化一定成功
            window.addEventListener("load", this.hashChange.bind(this));
            window.addEventListener('hashchange', this.hashChange.bind(this));
        }
    }
    hashChange() {
        this.data.current = window.location.hash.slice(1) || "/";
    }
}